#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "z_memory.h"
#include "z_logger.h"

static ssize_t _heap_size = 0;

typedef struct {
    size_t size;
    void *ptr;
} heap_ptr;

void z_debug() {
    log_debug("z_memory heap size: %zd", _heap_size);
}

static void _heap_debug_alloc(size_t __size, const char *file, int line, const char *func) {
    _heap_size += __size;
//    const log4c_location_info_t loc_info = {.loc_file = file, .loc_line = line, .loc_function =func};
//    log_category_location(&loc_info, LOG4C_PRIORITY_TRACE, "alloc=%zu, heap=%ld", __size, _heap_size);
}

static void _heap_debug_free(size_t __size, const char *file, int line, const char *func) {
    _heap_size -= __size;
//    const log4c_location_info_t loc_info = {.loc_file = file, .loc_line = line, .loc_function =func};
//    log_category_location(&loc_info, LOG4C_PRIORITY_TRACE, "free=%zu, heap=%ld", __size, _heap_size);
}

void *_z_malloc(size_t __size, const char *file, int line, const char *func) {
    heap_ptr *p = malloc(sizeof(int) + __size);
    p->size = __size;
    _heap_debug_alloc(p->size, file, line, func);
    return &p->ptr;
}

void *_z_calloc(size_t __nmemb, size_t __size, const char *file, int line, const char *func) {
    heap_ptr *p = calloc(1, sizeof(int) + __nmemb * __size);
    p->size = __nmemb * __size;
    _heap_debug_alloc(p->size, file, line, func);
    return &p->ptr;
}

void *_z_realloc(void *__ptr, size_t __size, const char *file, int line, const char *func) {
    heap_ptr *p = realloc(__ptr, __size);
    p->size = __size;
    _heap_debug_alloc(p->size, file, line, func);
    return &p->ptr;
}

void _z_free(void *__ptr, const char *file, int line, const char *func) {
    if (!__ptr)
        return;
    heap_ptr *p = __ptr - sizeof(p->size);
    _heap_debug_free(p->size, file, line, func);
    free(p);
}